/*
 * ticketinfo_dao.c
 *
 *  Created on: 2013-2-19
 *      Author: panqiuhui
 */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mysql.h>
#include <time.h>

#include "../head/dao/ticketinfo_dao.h"
#include "../head/dao/traininfo_dao.h"
#include "../head/dao/orderinfo_dao.h"

#define BUY_TICKET_STMT "SELECT s.compartmentNum, s.seatNum FROM seats s LEFT JOIN (SELECT * FROM orders WHERE trainID='%s' and departDate='%s') AS o ON (s.trainID = o.trainID AND s.compartmentNum = o.compartmentNum AND s.seatNum = o.seatNum) WHERE s.trainID = '%s' AND o.orderID IS NULL ORDER BY s.compartmentNum, s.seatNum ASC"

//插入一条订单，成功返回true并将order中的orderID填充，失败返回false
bool insert_order_for_ticket(struct orderinfo *order);
//判断一个车站是否到售票时间
bool is_start_sale_ticket(const char *stationName);
//判断两个字符串形式的时间的先后，如果first_time比second_time晚，返回false，否则返回true
bool compare_time_early_equal(const char *first_time, const char *second_time);
//判断两个字符串形式的时间的先后，如果first_time比second_time早，返回false，否则返回true
bool compare_time_late_equal(const char *first_time, const char *second_time);
//计算一个车次一共有多少座位
int calculate_seat_count(const char *trainID);
//计算一个车次已经卖出多少张票
int calculate_ticket_saled(const char *trainID, const char *departDate);

extern MYSQL connection;
extern MYSQL_STMT *get_traininfo_for_ticketleft_stmt;
extern MYSQL_STMT *get_traininfo_for_ticketleft_with_trainID_stmt;
extern MYSQL_STMT *get_train_seatcount_stmt;
extern MYSQL_STMT *get_train_sale_ticketcount_stmt;
extern MYSQL_STMT *insert_orderinfo_stmt;

enum {
	INPUT_INSERT_ORDERINFO_TRAINID = 0,
	INPUT_INSERT_ORDERINFO_COMPARTMENTNUM,
	INPUT_INSERT_ORDERINFO_SEATNUM,
	INPUT_INSERT_ORDERINFO_USERNAME,
	INPUT_INSERT_ORDERINFO_DEPARTDATE,
	INPUT_INSERT_ORDERINFO_DEPARTSTATION,
	INPUT_INSERT_ORDERINFO_ARRIVESTATION,
	INPUT_INSERT_ORDERINFO_BUYDATE,
	INPUT_INSERT_ORDERINFO_PRICE,
	INPUT_INSERT_ORDERINFO_COLUMN_NUM
};

enum {
	INPUT_TRAIN_SEATCOUNT_TRAINID = 0, INPUT_TRAIN_SEATCOUNT_COLUMN_NUM
};

enum {
	OUTPUT_TRAIN_SEATCOUNT_COMPARTMENTNUM = 0,
	OUTPUT_TRAIN_SEATCOUNT_SEATCOUNT,
	OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM
};

enum {
	INPUT_SALE_TICKETCOUNT_TRAINID = 0,
	INPUT_SALE_TICKETCOUNT_DEPARTDATE,
	INPUT_SALE_TICKETCOUNT_COLUMN_NUM
};

enum {
	OUTPUT_SALE_TICKETCOUNT_TICKETSALEDCOUNT = 0,
	OUTPUT_SALE_TICKETCOUNT_COLUMN_NUM
};

enum {
	INPUT_TRAININFO_FOR_TICKETLEFT_STARTSTATION_CITY = 0,
	INPUT_TRAININFO_FOR_TICKETLEFT_ENDSTATION_CITY,
	INPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE,
	INPUT_TRAININFO_FOR_TICKETLEFT_TRAINID,
	INPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM
};

enum {
	OUTPUT_TRAININFO_FOR_TICKETLEFT_TRAINID = 0,
	OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTSTATION,
	OUTPUT_TRAININFO_FOR_TICKETLEFT_ARRIVESTATION,
	OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE,
	OUTPUT_TRAININFO_FOR_TICKETLEFT_PRICE,
	OUTPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM
};

//买票，成功返回true并将票的信息保存在ticket中，购买失败返回false
bool buy_ticket(const struct buy_ticket_request *request,
		struct ticket_saled_info *ticket) {
	bool result = true;
	int len =
			strlen(
					BUY_TICKET_STMT)+TRAINS_TRAINID_LEN+TRAINS_DEPARTDATE_LEN+TRAINS_TRAINID_LEN;
	char sql[len];
	memset(sql, 0, sizeof(sql));
	sprintf(sql, BUY_TICKET_STMT, request->trainID, request->departDate,
			request->trainID);
	int comparmentNum;
	int seatNum;

	MYSQL_RES *res_ptr;
	MYSQL_ROW row;
	int res;

	res = mysql_query(&connection, sql);

	if (res) {
		printf("buy ticket sql error: %s\n", mysql_error(&connection));
		result = false;
	} else {
		res_ptr = mysql_use_result(&connection);
		if (res_ptr) {
			while ((row = mysql_fetch_row(res_ptr))) {
				sscanf(row[0], "%d", &comparmentNum);
				sscanf(row[1], "%d", &seatNum);

				struct traininfo train;
				memset(&train, 0, sizeof(train));
				bool ishave = true;
				ishave = get_traininfo(request->trainID, &train); //得到一个车次的详细信息
				if (!ishave) { //如果没找到该车次信息，继续下一循环，现实中这种情况不应该存在
					continue;
				}

				struct orderinfo order;
				memset(&order, 0, sizeof(order));
				sprintf(order.trainID, "%s", request->trainID);
				sprintf(order.compartmentNum, "%d", comparmentNum);
				sprintf(order.seatNum, "%d", seatNum);
				sprintf(order.name, "%s", request->username);
				sprintf(order.departDate, "%s", request->departDate);
				sprintf(order.departStation, "%s", request->departStation);
				sprintf(order.arriveStation, "%s", request->arriveStation);
				sprintf(order.price, "%-10.2f", request->price);

				struct tm *tm_ptr;
				time_t the_time;
				(void) time(&the_time);
				tm_ptr = localtime(&the_time);
				sprintf(order.buyDate, "%04d-%02d-%02d", tm_ptr->tm_year + 1900,
						tm_ptr->tm_mon + 1, tm_ptr->tm_mday);

				bool is_ok = true;
				is_ok = insert_order_for_ticket(&order);
				if (is_ok) {
					ticket->train = train;
					ticket->order = order;
				} else {
					result = false;
					continue;
				}
				break;
			}
			mysql_free_result(res_ptr);
		} else {
			result = false;
		}
	}
	return result;
}

//插入一条订单，成功返回true并将order中的orderID填充，失败返回false
bool insert_order_for_ticket(struct orderinfo *order) {
	bool result = true;
	//设置输入的参数信息
	MYSQL_BIND input_bind[INPUT_INSERT_ORDERINFO_COLUMN_NUM];
	char input_trainID[TRAINS_TRAINID_LEN];
	unsigned long input_trainID_len;
	int input_compartmentNum;
	int input_seatNum;
	char input_username[ORDERS_USERNAME_LEN];
	unsigned long input_username_len;
	MYSQL_TIME input_departDate;
	char input_departStation[ORDERS_DEPART_STATION_LEN];
	unsigned long input_departStation_len;
	char input_arriveStation[ORDERS_ARRIVE_STATION_LEN];
	unsigned long input_arriveStation_len;
	MYSQL_TIME input_buyDate;
	float input_price;

	memset(input_trainID, 0, sizeof(input_trainID));
	strncpy(input_trainID, order->trainID, strlen(order->trainID));
	input_trainID_len = strlen(input_trainID);

	sscanf(order->compartmentNum, "%d", &input_compartmentNum);
	sscanf(order->seatNum, "%d", &input_seatNum);

	memset(input_username, 0, sizeof(input_username));
	strncpy(input_username, order->name, strlen(order->name));
	input_username_len = strlen(input_username);

	int input_departDate_year;
	int input_departDate_month;
	int input_departDate_day;
	sscanf(order->departDate, "%04d-%02d-%02d", &input_departDate_year,
			&input_departDate_month, &input_departDate_day);
	input_departDate.year = input_departDate_year;
	input_departDate.month = input_departDate_month;
	input_departDate.day = input_departDate_day;

	memset(input_departStation, 0, sizeof(input_departStation));
	strncpy(input_departStation, order->departStation,
			strlen(order->departStation));
	input_departStation_len = strlen(input_departStation);

	memset(input_arriveStation, 0, sizeof(input_arriveStation));
	strncpy(input_arriveStation, order->arriveStation,
			strlen(order->arriveStation));
	input_arriveStation_len = strlen(input_arriveStation);

	int input_buyDate_year;
	int input_buytDate_month;
	int input_buytDate_day;
	sscanf(order->buyDate, "%04d-%02d-%02d", &input_buyDate_year,
			&input_buytDate_month, &input_buytDate_day);
	input_buyDate.year = input_buyDate_year;
	input_buyDate.month = input_buytDate_month;
	input_buyDate.day = input_buytDate_day;

	sscanf(order->price, "%f", &input_price);

	memset(input_bind, 0, sizeof(input_bind));
	input_bind[INPUT_INSERT_ORDERINFO_TRAINID].buffer_type = MYSQL_TYPE_STRING;
	input_bind[INPUT_INSERT_ORDERINFO_TRAINID].buffer = input_trainID;
	input_bind[INPUT_INSERT_ORDERINFO_TRAINID].buffer_length =
			TRAINS_TRAINID_LEN;
	input_bind[INPUT_INSERT_ORDERINFO_TRAINID].is_null = 0;
	input_bind[INPUT_INSERT_ORDERINFO_TRAINID].length = &input_trainID_len;

	input_bind[INPUT_INSERT_ORDERINFO_COMPARTMENTNUM].buffer_type =
			MYSQL_TYPE_LONG;
	input_bind[INPUT_INSERT_ORDERINFO_COMPARTMENTNUM].buffer =
			&input_compartmentNum;
	input_bind[INPUT_INSERT_ORDERINFO_COMPARTMENTNUM].is_null = 0;

	input_bind[INPUT_INSERT_ORDERINFO_SEATNUM].buffer_type = MYSQL_TYPE_LONG;
	input_bind[INPUT_INSERT_ORDERINFO_SEATNUM].buffer = &input_seatNum;
	input_bind[INPUT_INSERT_ORDERINFO_SEATNUM].is_null = 0;

	input_bind[INPUT_INSERT_ORDERINFO_USERNAME].buffer_type = MYSQL_TYPE_STRING;
	input_bind[INPUT_INSERT_ORDERINFO_USERNAME].buffer = input_username;
	input_bind[INPUT_INSERT_ORDERINFO_USERNAME].buffer_length =
			ORDERS_USERNAME_LEN;
	input_bind[INPUT_INSERT_ORDERINFO_USERNAME].is_null = 0;
	input_bind[INPUT_INSERT_ORDERINFO_USERNAME].length = &input_username_len;

	input_bind[INPUT_INSERT_ORDERINFO_DEPARTDATE].buffer_type = MYSQL_TYPE_DATE;
	input_bind[INPUT_INSERT_ORDERINFO_DEPARTDATE].buffer = &input_departDate;
	input_bind[INPUT_INSERT_ORDERINFO_DEPARTDATE].is_null = 0;

	input_bind[INPUT_INSERT_ORDERINFO_DEPARTSTATION].buffer_type =
			MYSQL_TYPE_STRING;
	input_bind[INPUT_INSERT_ORDERINFO_DEPARTSTATION].buffer =
			input_departStation;
	input_bind[INPUT_INSERT_ORDERINFO_DEPARTSTATION].buffer_length =
			ORDERS_DEPART_STATION_LEN;
	input_bind[INPUT_INSERT_ORDERINFO_DEPARTSTATION].is_null = 0;
	input_bind[INPUT_INSERT_ORDERINFO_DEPARTSTATION].length =
			&input_departStation_len;

	input_bind[INPUT_INSERT_ORDERINFO_ARRIVESTATION].buffer_type =
			MYSQL_TYPE_STRING;
	input_bind[INPUT_INSERT_ORDERINFO_ARRIVESTATION].buffer =
			input_arriveStation;
	input_bind[INPUT_INSERT_ORDERINFO_ARRIVESTATION].buffer_length =
			ORDERS_ARRIVE_STATION_LEN;
	input_bind[INPUT_INSERT_ORDERINFO_ARRIVESTATION].is_null = 0;
	input_bind[INPUT_INSERT_ORDERINFO_ARRIVESTATION].length =
			&input_arriveStation_len;

	input_bind[INPUT_INSERT_ORDERINFO_BUYDATE].buffer_type = MYSQL_TYPE_DATE;
	input_bind[INPUT_INSERT_ORDERINFO_BUYDATE].buffer = &input_buyDate;
	input_bind[INPUT_INSERT_ORDERINFO_BUYDATE].is_null = 0;

	input_bind[INPUT_INSERT_ORDERINFO_PRICE].buffer_type = MYSQL_TYPE_FLOAT;
	input_bind[INPUT_INSERT_ORDERINFO_PRICE].buffer = &input_price;
	input_bind[INPUT_INSERT_ORDERINFO_PRICE].is_null = 0;

	if (mysql_stmt_bind_param(insert_orderinfo_stmt, input_bind)) {
		fprintf(stderr,
				"insert_orderinfo_stmt mysql_stmt_bind_param() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(insert_orderinfo_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_execute(insert_orderinfo_stmt)) {
		fprintf(stderr, "insert_orderinfo_stmt mysql_stmt_execute(), failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(insert_orderinfo_stmt));
		exit(EXIT_FAILURE);
	}

	int affected_rows = mysql_stmt_affected_rows(insert_orderinfo_stmt);
	/*fprintf(stdout, "insert_orderinfo_stmt total affected rows: %lu\n",
	 (unsigned long) affected_rows);*/

	if (affected_rows == 1) {
		MYSQL_RES *res_ptr;
		MYSQL_ROW sqlrow;
		int res;

		res = mysql_query(&connection, "SELECT LAST_INSERT_ID()");

		if (res) {
			printf("insert_orderinfo_stmt error: %s\n",
					mysql_error(&connection));
		} else {
			res_ptr = mysql_use_result(&connection);
			if (res_ptr) {
				while ((sqlrow = mysql_fetch_row(res_ptr))) {
					sscanf(sqlrow[0], "%s", order->orderID);
					break;
				}
				mysql_free_result(res_ptr);
			}
		}
	} else {
		result = false;
	}
	return result;
}

//查询余票信息，成功返回true并将结果添加到ticketlist中，失败返回false
bool search_ticket_left(const struct ticket_left_request *request,
		TicketList *ticketlist) {
	bool result = true;
//从ticketsinfo表中查找符合条件车次，暂不考虑始发终到以及列车的类型
//设置输入的参数信息
	MYSQL_BIND input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM];
	char input_start_station_city[STATIONS_CITY_LEN];
	unsigned long input_start_station_city_len = strlen(request->startAddress);
	char input_end_station_city[STATIONS_CITY_LEN];
	unsigned long input_end_station_city_len = strlen(request->endAddress);
	MYSQL_TIME input_departDate;
	char input_trainID[TRAINS_TRAINID_LEN];
	unsigned long input_trainID_len;
	MYSQL_STMT *stmtselected;

	memset(input_start_station_city, 0, sizeof(input_start_station_city));
	strncpy(input_start_station_city, request->startAddress,
			input_start_station_city_len);

	memset(input_end_station_city, 0, sizeof(input_end_station_city));
	strncpy(input_end_station_city, request->endAddress,
			input_end_station_city_len);

	int year;
	int month;
	int day;
	sscanf(request->departDate, "%04d-%02d-%02d", &year, &month, &day);
	input_departDate.year = year;
	input_departDate.month = month;
	input_departDate.day = day;

	memset(input_bind, 0, sizeof(input_bind));
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_STARTSTATION_CITY].buffer_type =
			MYSQL_TYPE_STRING;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_STARTSTATION_CITY].buffer =
			input_start_station_city;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_STARTSTATION_CITY].buffer_length =
			STATIONS_CITY_LEN;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_STARTSTATION_CITY].is_null = 0;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_STARTSTATION_CITY].length =
			&input_start_station_city_len;

	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_ENDSTATION_CITY].buffer_type =
			MYSQL_TYPE_STRING;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_ENDSTATION_CITY].buffer =
			input_end_station_city;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_ENDSTATION_CITY].buffer_length =
			STATIONS_CITY_LEN;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_ENDSTATION_CITY].is_null = 0;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_ENDSTATION_CITY].length =
			&input_end_station_city_len;

	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE].buffer_type =
			MYSQL_TYPE_DATE;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE].buffer =
			&input_departDate;
	input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE].is_null = 0;

	if (strlen(request->trainID) != 0) {
		input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].buffer_type =
				MYSQL_TYPE_STRING;
		input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].buffer =
				input_trainID;
		input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].buffer_length =
				TRAINS_TRAINID_LEN;
		input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].is_null = 0;
		input_bind[INPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].length =
				&input_trainID_len;

		memset(input_trainID, 0, sizeof(input_trainID));
		strncpy(input_trainID, request->trainID, strlen(request->trainID));
		input_trainID_len = strlen(input_trainID);

		stmtselected = get_traininfo_for_ticketleft_with_trainID_stmt;
	} else {
		stmtselected = get_traininfo_for_ticketleft_stmt;
	}

//设置输出的参数信息
	MYSQL_BIND output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM];
	char output_trainID[TRAINS_TRAINID_LEN];
	char output_departStation[TRAINS_DEPARTSTATIONS_LEN];
	char output_arriveStation[TRAINS_ARRIVESTATIONS_LEN];
	MYSQL_TIME output_departDate;
	float output_price;
	unsigned long output_length[OUTPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM];
	my_bool output_is_null[OUTPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM];
	my_bool output_error[OUTPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM];

	memset(output_bind, 0, sizeof(output_bind));
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].buffer_type =
			MYSQL_TYPE_STRING;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].buffer =
			output_trainID;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_TRAINID].buffer_length =
			TRAINS_TRAINID_LEN;

	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTSTATION].buffer_type =
			MYSQL_TYPE_STRING;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTSTATION].buffer =
			output_departStation;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTSTATION].buffer_length =
			TRAINS_DEPARTSTATIONS_LEN;

	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_ARRIVESTATION].buffer_type =
			MYSQL_TYPE_STRING;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_ARRIVESTATION].buffer =
			output_arriveStation;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_ARRIVESTATION].buffer_length =
			TRAINS_ARRIVESTATIONS_LEN;

	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE].buffer_type =
			MYSQL_TYPE_DATE;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE].buffer =
			&output_departDate;

	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_PRICE].buffer_type =
			MYSQL_TYPE_FLOAT;
	output_bind[OUTPUT_TRAININFO_FOR_TICKETLEFT_PRICE].buffer = &output_price;

	int i = 0;
	for (i = 0; i < OUTPUT_TRAININFO_FOR_TICKETLEFT_COLUMN_NUM; i++) {
		output_bind[i].is_null = &output_is_null[i];
		output_bind[i].length = &output_length[i];
		output_bind[i].error = &output_error[i];
	}

	if (mysql_stmt_bind_param(stmtselected, input_bind)) {
		fprintf(stderr,
				"get_traininfo_for_ticketleft_stmt mysql_stmt_bind_param() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(stmtselected));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_execute(stmtselected)) {
		fprintf(stderr,
				"get_traininfo_for_ticketleft_stmt mysql_stmt_execute(), failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(stmtselected));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_bind_result(stmtselected, output_bind)) {
		fprintf(stderr,
				"get_traininfo_for_ticketleft_stmt mysql_stmt_bind_result() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(stmtselected));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_store_result(stmtselected)) {
		fprintf(stderr,
				"get_traininfo_for_ticketleft_stmt mysql_stmt_store_result() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(stmtselected));
		exit(EXIT_FAILURE);
	}

	int rownum = mysql_stmt_num_rows(stmtselected);
//printf("get_traininfo_for_ticketleft_stmt rownums: %d\n", rownum);

	if (rownum > 0) {
		while (!mysql_stmt_fetch(stmtselected)) {
			TicketItem item;
			memset(&item, 0, sizeof(item));
			if (!output_is_null[OUTPUT_TRAININFO_FOR_TICKETLEFT_TRAINID]) {
				sprintf(item.trainID, "%s", output_trainID);
			}
			if (!output_is_null[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTSTATION]) {
				sprintf(item.startStation, "%s", output_departStation);
			}
			if (!output_is_null[OUTPUT_TRAININFO_FOR_TICKETLEFT_ARRIVESTATION]) {
				sprintf(item.endStation, "%s", output_arriveStation);
			}
			if (!output_is_null[OUTPUT_TRAININFO_FOR_TICKETLEFT_DEPARTDATE]) {
				sprintf(item.departDate, "%04d-%02d-%02d",
						output_departDate.year, output_departDate.month,
						output_departDate.day);
			}
			if (!output_is_null[OUTPUT_TRAININFO_FOR_TICKETLEFT_PRICE]) {
				sprintf(item.price, "%-10.2f", output_price);
			}

			struct traininfo train;
			memset(&train, 0, sizeof(train));
			bool ishave = true;
			ishave = get_traininfo(item.trainID, &train); //得到一个车次的详细信息
			if (!ishave) { //如果没找到该车次信息，继续下一循环，现实中这种情况不应该存在
				continue;
			}

			bool is_ok = true;
			is_ok = check_train_type(request->trainType, train.trainID); //检查车次是否符合类型条件
			if (!is_ok) {
				continue;
			}
			is_ok = check_depart_arrive_station(request->passStationType,
					&train, input_start_station_city, input_end_station_city); //检查车次是否符合始发终到条件
			if (!is_ok) {
				continue;
			}

			struct stations_timeinfo timeinfo;
			memset(&timeinfo, 0, sizeof(timeinfo));
			is_ok = get_start_end_consume_timeinfo(train.trainID,
					output_departStation, output_arriveStation, &timeinfo); //得到车站的发时、到时以及历时信息
			if (!is_ok) {
				continue;
			}

			is_ok = (compare_time_early_equal(request->timeRangeLow,
					timeinfo.startTime))
					&& (compare_time_late_equal(request->timeRangeHigh,
							timeinfo.startTime)); //检查车站的发车时间是否符合出发时间区间
			if (!is_ok) {
				continue;
			}

			sprintf(item.startTime, "%s", timeinfo.startTime);
			sprintf(item.endTime, "%s", timeinfo.endTime);
			sprintf(item.consumeTime, "%s", timeinfo.consumeTime);

			if (is_start_sale_ticket(output_departStation)) {
				item.isStartSale = true;
				int seatCount = 0;
				seatCount = calculate_seat_count(item.trainID);
				int saleTicketCount = 0;
				saleTicketCount = calculate_ticket_saled(train.trainID,
						request->departDate);
				int ticket_left = seatCount - saleTicketCount;
				item.ticketLeft = ticket_left;
			} else {
				item.isStartSale = false;
			}

			if (strcmp(output_departStation, train.departStation) == 0) {
				item.isDepartStation = true;
			} else {
				item.isDepartStation = false;
			}

			if (strcmp(output_arriveStation, train.arriveStation) == 0) {
				item.isArriveStation = true;
			} else {
				item.isArriveStation = false;
			}

			AddItemTicket(item, ticketlist);
		}
		if (ListItemCountTicket(ticketlist) == 0) {
			result = false;
		}
	} else {
		result = false;
	}
	return result;
}

//判断一个车站是否到售票时间
bool is_start_sale_ticket(const char *stationName) {
	bool result = true;
	struct stationinfo station;
	memset(&station, 0, sizeof(station));
	result = get_stationinfo(stationName, &station);
	if (result) {
		struct tm *tm_ptr;
		time_t the_time;
		(void) time(&the_time);
		tm_ptr = localtime(&the_time);
		char time[TRAINS_DEPARTTIME_LEN];
		memset(time, 0, sizeof(time));
		sprintf(time, "%02d:%02d", tm_ptr->tm_hour, tm_ptr->tm_min);
		//printf("time:%s\n", time);

		if (compare_time_early_equal(time, station.startSaleTime)) {
			result = false;
		}
	}
	return result;
}

//判断两个字符串形式的时间的先后，如果first_time比second_time晚，返回false，否则返回true
bool compare_time_early_equal(const char *first_time, const char *second_time) {
	bool result = true;
	int first_time_hour;
	int first_time_minute;
	int second_time_hour;
	int second_time_minute;
	sscanf(first_time, "%02d:%02d", &first_time_hour, &first_time_minute);
	sscanf(second_time, "%02d:%02d", &second_time_hour, &second_time_minute);

	if (first_time_hour == second_time_hour) {
		if (first_time_minute > second_time_minute) {
			result = false;
		}
	} else if (first_time_hour > second_time_hour) {
		result = false;
	}
	return result;
}

//判断两个字符串形式的时间的先后，如果first_time比second_time早，返回false，否则返回true
bool compare_time_late_equal(const char *first_time, const char *second_time) {
	bool result = true;
	int first_time_hour;
	int first_time_minute;
	int second_time_hour;
	int second_time_minute;
	sscanf(first_time, "%02d:%02d", &first_time_hour, &first_time_minute);
	sscanf(second_time, "%02d:%02d", &second_time_hour, &second_time_minute);

	if (first_time_hour == second_time_hour) {
		if (first_time_minute < second_time_minute) {
			result = false;
		}
	} else if (first_time_hour < second_time_hour) {
		result = false;
	}
	return result;
}

//计算一个车次一共有多少座位
int calculate_seat_count(const char *trainID) {
	int seatCount = 0;
//设置输入的参数信息
	MYSQL_BIND input_bind[INPUT_TRAIN_SEATCOUNT_COLUMN_NUM];
	char input_trainID[TRAINS_TRAINID_LEN];
	unsigned long input_trainID_len;

	memset(input_bind, 0, sizeof(input_bind));
	input_bind[INPUT_TRAIN_SEATCOUNT_TRAINID].buffer_type = MYSQL_TYPE_STRING;
	input_bind[INPUT_TRAIN_SEATCOUNT_TRAINID].buffer = input_trainID;
	input_bind[INPUT_TRAIN_SEATCOUNT_TRAINID].buffer_length =
			TRAINS_TRAINID_LEN;
	input_bind[INPUT_TRAIN_SEATCOUNT_TRAINID].is_null = 0;
	input_bind[INPUT_TRAIN_SEATCOUNT_TRAINID].length = &input_trainID_len;

	memset(input_trainID, 0, sizeof(input_trainID));
	strncpy(input_trainID, trainID, strlen(trainID));
	input_trainID_len = strlen(input_trainID);

//设置输出的参数信息
	MYSQL_BIND output_bind[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];
	int output_compartmentNum;
	int output_seatCount;
	unsigned long output_length[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];
	my_bool output_is_null[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];
	my_bool output_error[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];

	memset(output_bind, 0, sizeof(output_bind));
	output_bind[OUTPUT_TRAIN_SEATCOUNT_COMPARTMENTNUM].buffer_type =
			MYSQL_TYPE_LONG;
	output_bind[OUTPUT_TRAIN_SEATCOUNT_COMPARTMENTNUM].buffer =
			&output_compartmentNum;

	output_bind[OUTPUT_TRAIN_SEATCOUNT_SEATCOUNT].buffer_type = MYSQL_TYPE_LONG;
	output_bind[OUTPUT_TRAIN_SEATCOUNT_SEATCOUNT].buffer = &output_seatCount;

	int i = 0;
	for (i = 0; i < OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM; i++) {
		output_bind[i].is_null = &output_is_null[i];
		output_bind[i].length = &output_length[i];
		output_bind[i].error = &output_error[i];
	}

	if (mysql_stmt_bind_param(get_train_seatcount_stmt, input_bind)) {
		fprintf(stderr,
				"get_train_seatcount_stmt mysql_stmt_bind_param() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(get_train_seatcount_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_execute(get_train_seatcount_stmt)) {
		fprintf(stderr,
				"get_train_seatcount_stmt mysql_stmt_execute(), failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(get_train_seatcount_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_bind_result(get_train_seatcount_stmt, output_bind)) {
		fprintf(stderr,
				"get_train_seatcount_stmt mysql_stmt_bind_result() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(get_train_seatcount_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_store_result(get_train_seatcount_stmt)) {
		fprintf(stderr,
				"get_train_seatcount_stmt mysql_stmt_store_result() failed\n");
		fprintf(stderr, "%s\n", mysql_stmt_error(get_train_seatcount_stmt));
		exit(EXIT_FAILURE);
	}

	int rownum = mysql_stmt_num_rows(get_train_seatcount_stmt);
//printf("get_train_seatcount_stmt rownums: %d\n", rownum);

	if (rownum > 0) {
		while (!mysql_stmt_fetch(get_train_seatcount_stmt)) {
			if (!output_is_null[OUTPUT_TRAIN_SEATCOUNT_SEATCOUNT]) {
				seatCount += output_seatCount;
			}
		}
	} else {
		seatCount = 0;
	}
	return seatCount;
}

//计算一个车次已经卖出多少张票
int calculate_ticket_saled(const char *trainID, const char *departDate) {
	int ticketSaled = 0;
//设置输入的参数信息
	MYSQL_BIND input_bind[INPUT_SALE_TICKETCOUNT_COLUMN_NUM];
	char input_trainID[TRAINS_TRAINID_LEN];
	unsigned long input_trainID_len;
	MYSQL_TIME input_departDate;

	memset(input_bind, 0, sizeof(input_bind));
	input_bind[INPUT_SALE_TICKETCOUNT_TRAINID].buffer_type = MYSQL_TYPE_STRING;
	input_bind[INPUT_SALE_TICKETCOUNT_TRAINID].buffer = input_trainID;
	input_bind[INPUT_SALE_TICKETCOUNT_TRAINID].buffer_length =
			TRAINS_TRAINID_LEN;
	input_bind[INPUT_SALE_TICKETCOUNT_TRAINID].is_null = 0;
	input_bind[INPUT_SALE_TICKETCOUNT_TRAINID].length = &input_trainID_len;

	input_bind[INPUT_SALE_TICKETCOUNT_DEPARTDATE].buffer_type = MYSQL_TYPE_DATE;
	input_bind[INPUT_SALE_TICKETCOUNT_DEPARTDATE].buffer = &input_departDate;
	input_bind[INPUT_SALE_TICKETCOUNT_DEPARTDATE].is_null = 0;

	memset(input_trainID, 0, sizeof(input_trainID));
	strncpy(input_trainID, trainID, strlen(trainID));
	input_trainID_len = strlen(input_trainID);

	int year;
	int month;
	int day;
	sscanf(departDate, "%04d-%02d-%02d", &year, &month, &day);
	input_departDate.year = year;
	input_departDate.month = month;
	input_departDate.day = day;

//设置输出的参数信息
	MYSQL_BIND output_bind[OUTPUT_SALE_TICKETCOUNT_COLUMN_NUM];
	int output_ticket_saled_count;
	unsigned long output_length[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];
	my_bool output_is_null[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];
	my_bool output_error[OUTPUT_TRAIN_SEATCOUNT_COLUMN_NUM];

	memset(output_bind, 0, sizeof(output_bind));
	output_bind[OUTPUT_SALE_TICKETCOUNT_TICKETSALEDCOUNT].buffer_type =
			MYSQL_TYPE_LONG;
	output_bind[OUTPUT_SALE_TICKETCOUNT_TICKETSALEDCOUNT].buffer =
			&output_ticket_saled_count;

	int i = 0;
	for (i = 0; i < OUTPUT_SALE_TICKETCOUNT_COLUMN_NUM; i++) {
		output_bind[i].is_null = &output_is_null[i];
		output_bind[i].length = &output_length[i];
		output_bind[i].error = &output_error[i];
	}

	if (mysql_stmt_bind_param(get_train_sale_ticketcount_stmt, input_bind)) {
		fprintf(stderr,
				"get_train_sale_ticketcount_stmt mysql_stmt_bind_param() failed\n");
		fprintf(stderr, "%s\n",
				mysql_stmt_error(get_train_sale_ticketcount_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_execute(get_train_sale_ticketcount_stmt)) {
		fprintf(stderr,
				"get_train_sale_ticketcount_stmt mysql_stmt_execute(), failed\n");
		fprintf(stderr, "%s\n",
				mysql_stmt_error(get_train_sale_ticketcount_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_bind_result(get_train_sale_ticketcount_stmt, output_bind)) {
		fprintf(stderr,
				"get_train_sale_ticketcount_stmt mysql_stmt_bind_result() failed\n");
		fprintf(stderr, "%s\n",
				mysql_stmt_error(get_train_sale_ticketcount_stmt));
		exit(EXIT_FAILURE);
	}

	if (mysql_stmt_store_result(get_train_sale_ticketcount_stmt)) {
		fprintf(stderr,
				"get_train_sale_ticketcount_stmt mysql_stmt_store_result() failed\n");
		fprintf(stderr, "%s\n",
				mysql_stmt_error(get_train_sale_ticketcount_stmt));
		exit(EXIT_FAILURE);
	}

	int rownum = mysql_stmt_num_rows(get_train_sale_ticketcount_stmt);
//printf("get_train_sale_ticketcount_stmt rownums: %d\n", rownum);

	if (rownum > 0) {
		while (!mysql_stmt_fetch(get_train_sale_ticketcount_stmt)) {
			if (!output_is_null[OUTPUT_SALE_TICKETCOUNT_TICKETSALEDCOUNT]) {
				ticketSaled = output_ticket_saled_count;
			}
			break;
		}
	} else {
		ticketSaled = 0;
	}
	return ticketSaled;
}
